package main

import (
	"fmt"
	"golang.org/x/net/webdav"
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
)

var modelContent string
var once = sync.Once{}

func getFolderModel() string {
	once.Do(func() {
		dir_model, open_err := os.ReadFile("folder.html")
		if open_err != nil {
			fmt.Println("打开目录页面模板失败", open_err)
			modelContent = ""
		}
		modelContent = string(dir_model)
		fmt.Println(modelContent)
	})
	return modelContent
}

func formatFileSize(size int64) string {
	const (
		B = 1 << (10 * iota)
		KB
		MB
		GB
		TB
		PB
		EB
	)

	switch {
	case size < KB:
		return fmt.Sprintf("%d B", size)
	case size < MB:
		return fmt.Sprintf("%.2f KB", float64(size)/float64(KB))
	case size < GB:
		return fmt.Sprintf("%.2f MB", float64(size)/float64(MB))
	case size < TB:
		return fmt.Sprintf("%.2f GB", float64(size)/float64(GB))
	case size < PB:
		return fmt.Sprintf("%.2f TB", float64(size)/float64(TB))
	case size < EB:
		return fmt.Sprintf("%.2f PB", float64(size)/float64(PB))
	default:
		return fmt.Sprintf("%.2f ZB", float64(size))
	}
}

func main() {
	root := "D:/data"
	handler := &webdav.Handler{
		FileSystem: webdav.Dir(root),
		LockSystem: webdav.NewMemLS(),
		Logger: func(r *http.Request, err error) {
			if err != nil {
				log.Printf("WebDAV error: %v", err)
			}
		},
	}

	//http.Handle("/", handler)
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "GET" {
			path := r.URL.Path
			file, err := handler.FileSystem.OpenFile(r.Context(), path, 0, 0)
			if err != nil {
				http.Error(w, "File not found", http.StatusNotFound)
				return
			}
			defer file.Close()

			info, err := file.Stat()
			if err != nil {
				http.Error(w, "Failed to get file info", http.StatusInternalServerError)
				return
			}

			if info.IsDir() {
				files, err := file.Readdir(-1)
				if err != nil {
					http.Error(w, "Failed to read directory", http.StatusInternalServerError)
					return
				}
				model := getFolderModel()
				model = strings.Replace(model, "###folder_path", path, -1)

				var file_list []string
				var folder_list []string
				for _, f := range files {
					if f.IsDir() {
						a_html := "<a href=\"" + path + f.Name() + "/\">"
						a_content := fmt.Sprintf("%s%s/</a>  %s        -", a_html, f.Name(), f.ModTime().Format("2006-01-02 15:04:05"))
						folder_list = append(folder_list, a_content)
					} else {
						a_html := "<a href=\"" + path + f.Name() + "\">"
						a_content := fmt.Sprintf("%s%s</a>  %s     %s", a_html, f.Name(), f.ModTime().Format("2006-01-02 15:04:05"), formatFileSize(f.Size()))
						//a_content := f.Name()[:58] + f.ModTime() + "</a>"
						//a_content := ("%-52s" % a_content) + string(f.ModTime())
						//a_content = a_content + '                 -'
						//a_html += a_content + '\n'
						file_list = append(file_list, a_content)
					}
				}

				spr := ""
				if len(folder_list) > 0 {
					spr = "\n"
				}
				file_list_content := strings.Join(folder_list, "\n") + spr + strings.Join(file_list, "\n")
				w.Write([]byte(strings.Replace(model, "#alist", file_list_content, -1)))
			} else {
				http.ServeContent(w, r, info.Name(), info.ModTime(), file)
			}
		} else {
			handler.ServeHTTP(w, r)
		}
	})

	log.Fatal(http.ListenAndServe(":8111", nil))
}
